package top.ninwoo.edgecenter.check;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.junit.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import top.ninwoo.common.entity.ClusterConfig;
import top.ninwoo.common.entity.ContainerDescription;
import top.ninwoo.common.entity.DockerContainer;
import top.ninwoo.common.entity.NetworkTopology;
import top.ninwoo.edgecenter.service.ClusterService;
import top.ninwoo.edgecenter.service.IpService;
import top.ninwoo.edgecenter.service.TopologyService;
import top.ninwoo.utils.service.DockerService;
import top.ninwoo.utils.util.LinuxCtlUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * Docker容器集群服务自检程序
 *
 * @author joliu
 */
@Slf4j
@Component
public class ClusterServiceCheck {
    @Autowired
    private ClusterService clusterService;
    @Autowired
    private DockerService dockerService;

    @Autowired
    private TopologyService topologyService;

    @Autowired
    private LinuxCtlUtils linuxCtlUtils;

    @Autowired
    private IpService ipService;

    private String container1Id;

    private String container2Id;

    private final static Long CLUSTERID = 12345L;

    public void createCluster() {
        log.info("启动容器自检服务");
        // 构建一个容器组配置
        ClusterConfig clusterConfig = new ClusterConfig();
        clusterConfig.setId(CLUSTERID);
        clusterConfig.setOwner("joliu");
        ContainerDescription containerDescription = new ContainerDescription();
        containerDescription.setMode("normal");
        containerDescription.setReplicas(2);
        DockerContainer container = new DockerContainer();
        container.setName("Test1");
        container.setCommand("sh");
        container.setImage("joliu/networktest");
        containerDescription.setDockerContainer(container);

        List<ContainerDescription> cds = new ArrayList<>();
        cds.add(containerDescription);

        ContainerDescription containerDescription1 = new ContainerDescription();
        containerDescription1.setMode("normal");
        containerDescription1.setReplicas(1);
        DockerContainer container1 = new DockerContainer();
        container1.setName("Test2");
        container1.setCommand("sh");
        container1.setImage("joliu/networktest");
        containerDescription1.setDockerContainer(container1);

        cds.add(containerDescription1);

        clusterConfig.setDockers(cds);

        NetworkTopology topo = new NetworkTopology();
        topo.setAppNames(new String[]{"Test1", "Test2", "br:ovs1"});
        // 这个参数好像没啥用
        topo.setTopologyId(11);
        topo.setTopology(new int[][]{{0,0,0},{0,0,0},{1,1,0}});
        clusterConfig.setTopology(topo);

        //long id = clusterService.initContainers(clusterConfig).getId();
        //Assert.assertEquals(id, clusterId);
        log.info("创建自检容器集群【Test1_0,Test1_1,Test2】");
        try {
            clusterService.initContainers(clusterConfig);
        } catch (Exception e) {
            log.error("容器启动失败");
            throw new RuntimeException("容器启动失败");
        }
        try {
            topologyService.createTopo(clusterConfig.getId(), clusterConfig.getTopology());
        } catch (Exception e) {
            log.error("容器网络初始化失败", e);
            throw new RuntimeException("容器网络初始化失败");
        }
        if(!clusterService.getClusterIds().contains(CLUSTERID)) {
            log.error("集群创建失败%", CLUSTERID);
        }
        log.info("容器集群[{}]创建成功", CLUSTERID);
        Set<String> test1 = clusterService.getContainerIdsByClusterId(CLUSTERID, "Test1");
        log.info("容器Test1副本创建成功：[{}]", test1);
        Set<String> test2 = clusterService.getContainerIdsByClusterId(CLUSTERID, "Test2");
        log.info("容器Test2副本创建成功：[{}]", test2);
        log.info("容器集群网络创建成功");
        container1Id = ((String) test1.toArray()[0]);
        container2Id = ((String) test2.toArray()[0]);
    }

    public void pingTest() {
        // 测试网络
        String ovsResult = linuxCtlUtils.runCmd("echo Vudo3423 | sudo -S ovs-vsctl show");
        log.info("Open vSwitch：{}", ovsResult);
        // 获取container2的ip
        // ifconfig eth1 |sed -rn '2s#^.*dr:(.*)  Bc.*$#\1#gp'
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String containerIp = ipService.getContainerIp(container2Id);
        if(StringUtils.isEmpty(containerIp)) {
            log.error("没有查询对应的容器IP,请检查IpService服务以及CreateTopo的服务");
        }
        String cid2Ip = containerIp.split("/")[0];
        log.info("容器1{} ping 容器2{} IP {}", container1Id, container2Id, cid2Ip);
        String pingResult = dockerService.execInDocker(container1Id, new String[]{"ping", cid2Ip, "-c", "4"});
        log.info("Ping Result:{}", pingResult);
        log.info("容器网络连通性测试成功");
    }

    public void delCluster() {
        try {
            clusterService.removeContainersByClusterId(CLUSTERID);
        } catch (Exception e) {
            log.warn("容器删除失败");
        }
        log.info("容器集群[{}]删除成功", CLUSTERID);
    }

    public void delNetworkTopo() {
        log.info("开始删除测试容器网络");
        topologyService.removeTopoByCluterId(12345L);
        log.info("测试集群：{}:删除成功");
    }
}
